export interface options {
    delay: number,
    //是否在延迟开始前调用函数
    leading?: boolean,
    //是否在延迟开始后调用函数
    trailing?: boolean,
    //最大等待时间
    maxWait?: number
}

export interface Result {
    run: (...args: any[]) => unknown,
    cancel: () => void
}

/**
 * @param fn 执行函数
 * @param options 防抖配置：delay延迟时间（默认1000ms），leading是否在延迟开始前调用函数，trailing是否在延迟开始后调用函数，maxWait最大等待时间
 * @returns 
 */
export function useDebounce(fn: () => unknown, options: options): Result{
    
    let timer: any;
    let max_timer: any;
    let run_trailing: boolean = false

    const debounce = function() {

        const context = this;

        const args: any = arguments;

        // 防抖开始前调用函数
        if(options.leading && !timer) {
            fn.apply(context, args);
        }

        // 防抖开始后调用函数
        if(options.trailing && timer && !run_trailing) {
            run_trailing = true
            fn.apply(context, args);
        }

        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(context, args);
            cancel()
        }, options.delay || 1000);

        //最大等待时间
        if(options.maxWait && !max_timer){
            max_timer = setTimeout(() => {
                fn.apply(context, args);
                cancel()
            }, options.maxWait)
        }
    }

    function cancel(){

        clearTimeout(timer)
        timer = null

        clearTimeout(max_timer)
        max_timer = null
        run_trailing = false
    }

    return {
        run: debounce,
        cancel: cancel
    }
}